﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using MtgLib;
using System.ComponentModel;
using System.Drawing;

namespace MtgPrinter
{
    [Serializable]
    public enum EExportPdfPageSize : int
    {
        Unknown = 0, A4, Letter, Legal
    };

    public static class Exporters
    {
        public static void exportToTxt(string filename, List<DeckEntry> deck)
        {
            if (File.Exists(filename)) File.Delete(filename);

            using (Stream fstr = File.OpenWrite(filename))
            {
                TextWriter twr = new StreamWriter(fstr);
                foreach (DeckEntry de in deck)
                {
                    twr.WriteLine(de.Quantity + "x " + de.CardName);
                }
                twr.Close();
                twr.Dispose();
            }
        }

        public delegate void ReportExportingProgress(float percent);

        public static void exportToPdf(string file, List<DeckEntry> deck, EExportPdfPageSize pageSize, ReportExportingProgress progressDelegate)
        {
            string filename = file;

            const float a4mm_x = 210;
            const float a4mm_y = 297;
            const float letter_mm_x = 215.9f;
            const float letter_mm_y = 279.4f;
            const float legal_mm_x = 216;
            const float legal_mm_y = 356;

            float px;
            float py;

            FileInfo fi = new FileInfo(filename);
            if (fi.Exists) fi.Delete();
            
            iTextSharp.text.Document doc;

            switch(pageSize)
            {
                case(EExportPdfPageSize.Legal):
                    doc = new iTextSharp.text.Document(iTextSharp.text.PageSize.LEGAL);
                    px = (float)Program.AppConfig.CardWidthCM * 10.0f / legal_mm_x * iTextSharp.text.PageSize.LEGAL.Width;
                    py = (float)Program.AppConfig.CardHeightCM * 10.0f / legal_mm_y * iTextSharp.text.PageSize.LEGAL.Height;
    
                    break;
                case(EExportPdfPageSize.Letter):
                    doc = new iTextSharp.text.Document(iTextSharp.text.PageSize.LETTER);
                    px = (float)Program.AppConfig.CardWidthCM * 10.0f / letter_mm_x * iTextSharp.text.PageSize.LETTER.Width;
                    py = (float)Program.AppConfig.CardHeightCM * 10.0f / letter_mm_y * iTextSharp.text.PageSize.LETTER.Height;
                    break;
                case(EExportPdfPageSize.A4):
                default:
                    doc= new iTextSharp.text.Document(iTextSharp.text.PageSize.A4);
                    px = (float)Program.AppConfig.CardWidthCM * 10.0f / a4mm_x * iTextSharp.text.PageSize.A4.Width;
                    py = (float)Program.AppConfig.CardHeightCM * 10.0f / a4mm_y * iTextSharp.text.PageSize.A4.Height;
                    break;
            };

            float marginX = (doc.PageSize.Width-(float)Math.Floor((decimal)doc.PageSize.Width/(decimal)px)*px)/2;
            float marginY = (doc.PageSize.Height - (float)Math.Floor((decimal)doc.PageSize.Height / (decimal)py) * py) / 2;

            iTextSharp.text.pdf.PdfWriter writer = iTextSharp.text.pdf.PdfWriter.GetInstance(doc, File.Create(filename));
            doc.Open();
            writer.SetFullCompression();
            doc.NewPage();

            float x = marginX;
            float y = marginY;
            int which = 0;
            foreach (DeckEntry de in deck)
            {
                Image cardImage = MtgCardDownloader.GetCardImage(de.CardName);
                for (int i = 0; i < de.Quantity; i++)
                {
                    if (cardImage != null)
                    {
                        iTextSharp.text.Image img = iTextSharp.text.Image.GetInstance(cardImage, System.Drawing.Imaging.ImageFormat.Jpeg);
                        img.ScaleAbsolute(px , py );
                        img.SetAbsolutePosition(x, y);                      
                        doc.Add(img);
                        
                        x += img.ScaledWidth;
                        if (x >= doc.PageSize.Width || x + img.ScaledWidth >= doc.PageSize.Width)
                        {
                            x = marginX;
                            y += img.ScaledHeight;

                        }
                        if (y >= doc.PageSize.Height || y + img.ScaledHeight >= doc.PageSize.Height)
                        {
                            x = marginX;
                            y = marginY;
                            doc.NewPage();
                        }
                    }
                    x++;
                }
                if (cardImage != null) cardImage.Dispose();
                if (progressDelegate != null) progressDelegate((float)++which / deck.Count);
            }
            doc.Close();
        }

        private static string getDefaultCardPictureFilename(string cardName)
        {
            return cardName.Replace(' ', '_') + ".jpg";
        }

        public static void exportToHtml(string filename,List<DeckEntry> deck, Graphics g, ReportExportingProgress progressDelegate)
        {
            decimal dpcmX = (decimal)g.DpiX / 2.54m;
            decimal dpcmY = (decimal)g.DpiX / 2.54m;

            int pxx = (int)(dpcmX * Program.AppConfig.CardWidthCM);
            int pyy = (int)(dpcmY * Program.AppConfig.CardHeightCM);
            g.Dispose();
            FileInfo fi = new FileInfo(filename);

            DirectoryInfo parentDir = Directory.GetParent(filename);
            string imagesPath = parentDir.ToString() + "\\" + fi.Name.Replace(".html", "") + "_Images\\";
            if (!Directory.Exists(imagesPath)) Directory.CreateDirectory(imagesPath);
            else
            {
                try
                {
                    Directory.Delete(imagesPath, true);
                    Directory.CreateDirectory(imagesPath);
                }
                catch (Exception) { }
            }

            foreach (DeckEntry de in deck)
            {
                string targetPath = imagesPath + getDefaultCardPictureFilename(de.CardName);
                Image cardImage = MtgCardDownloader.GetCardImage(de.CardName);
                if (cardImage != null)
                {
                    cardImage.Save(targetPath);
                }
                cardImage.Dispose();
            }

            using (Stream fle = File.Open(filename, FileMode.Create))
            {
                StreamWriter sw = new StreamWriter(fle);
                sw.WriteLine("<!DOCTYPE html PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\">");
                sw.WriteLine("<html>\n<head>");
                sw.WriteLine("<title>Mtg Deck</title>");
                sw.WriteLine("<style type=\"text/css\">");
                sw.WriteLine("img {");
                sw.WriteLine("width: " + pxx + "px;");
                sw.WriteLine("height: " + pyy + "px;");
                sw.WriteLine("margin-right: 1px;");
                sw.WriteLine("margin-bottom: 1px;");
                sw.WriteLine("margin-left: 0px;");
                sw.WriteLine("margin-top: 0px;");
                sw.WriteLine("padding: 0px;");
                sw.WriteLine("}");
                sw.WriteLine("body {");
                sw.WriteLine("padding: 0;");
                sw.WriteLine("margin: 0;");
                sw.WriteLine("border: none;");
                sw.WriteLine("}");
                sw.WriteLine("</style>");
                sw.WriteLine("</head>");
                sw.WriteLine("<body>");

                foreach (DeckEntry de in deck)
                {
                    for (int i = 0; i < de.Quantity; i++)
                    {
                        sw.Write("<img src=\"{0}{1}\" alt=\"{2}\"/>", fi.Name.Replace(".html", "") + "_Images/", getDefaultCardPictureFilename(de.CardName), de.CardName);
                    }
                }

                sw.WriteLine();
                sw.WriteLine("</body>");
                sw.WriteLine("</html>");

                sw.Close();
                sw.Dispose();
            }
        }
    }
}
